package com.maxjay.component.metadata.core.parser;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Component;

import com.maxjay.common.util.collection.CollectionUtil;
import com.maxjay.component.metadata.constant.GeneratorEnableType;
import com.maxjay.component.metadata.core.generator.DefaultFieldValueGenerator;
import com.maxjay.component.metadata.core.generator.FieldValueGenerator;
import com.maxjay.component.metadata.model.DefaultEntity;
import com.maxjay.component.metadata.model.DefaultEntityField;
import com.maxjay.component.metadata.model.Entity;
import com.maxjay.system.constant.SystemParamKeys;
import com.maxjay.system.core.Application;
import com.maxjay.system.core.cache.SystemDataHolder;

@Component("entityParser")
public class XmlEntityParser implements EntityParser {
	
	private static final String ENTITYCONF_PATH_PARAMKEY = "entityConfPath";
	
	private static final String DEFAULT_ENTITYCONF_PATH = "classpath:/component/metadata/entity.xml";
	
	@Override
	public Entity parseEntity(String entityId) {
		try {
			Element rootElement = getEntityRootElement(entityId);
			String nameCn = rootElement.element("display").getText();
			DefaultEntity entity = new DefaultEntity(entityId, entityId, nameCn);
			parseEntityFields(entity, rootElement);
			return entity;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 获取entity配置文件的根节点
	 * 
	 * @param entityId
	 * @return
	 */
	private Element getEntityRootElement(String entityId) throws Exception {
		String entityConfPath = SystemDataHolder.getInstance().getSystemParam(ENTITYCONF_PATH_PARAMKEY);
		String entityConfigPath = StringUtils.isBlank(entityConfPath) ? DEFAULT_ENTITYCONF_PATH : entityConfPath;
		Element entityRoot = null;
		URL url = null;
		if (entityConfigPath.indexOf("classpath:") == 0) {
			url = Thread.currentThread().getContextClassLoader().getResource(entityConfigPath.substring("classpath:".length()));
		} else {
			url = new URL(System.getProperty(SystemParamKeys.WEBCONTEXT_ROOT_PATH) + entityConfigPath);
		}
		if (url == null) {
			throw new RuntimeException("未能在类路径中找到文件:" + entityConfigPath);
		}
		try {
			InputStream in = null;
			InputStream confIn = null;
			try {
				in = url.openStream();
				Document document = new SAXReader().read(in);
				Element root = document.getRootElement();
				@SuppressWarnings("unchecked")
				List<Element> entityEls = root.elements("entity");
				for (Element entityEl : entityEls) {
					String name = entityEl.attributeValue("name");
					String file = entityEl.attributeValue("file");
					if(entityId.equals(name)) {
						URL confUrl = Thread.currentThread().getContextClassLoader().getResource(file);
						confIn = confUrl.openStream();
						Document entityDocument = new SAXReader().read(confIn);
						entityRoot = entityDocument.getRootElement();
						break;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if(in != null) {
					in.close();
				}
				if(confIn != null) {
					confIn.close();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return entityRoot;
	}
	
	/**
	 * 解析xml配置中<fields/>的实体字段信息
	 * 
	 * @param entity
	 * @param entityDocument
	 */
	@SuppressWarnings("unchecked")
	private void parseEntityFields(Entity entity, Element rootElement) throws Exception {
		Element fieldsElement = rootElement.element("fields");
		// 解析key-field节点
		Element keyElement = fieldsElement.element("key-field");
		DefaultEntityField keyField = parseEntityField(keyElement);
		keyField.setKey(true);
		entity.addEntityField(keyField);
		
		// 解析field节点
		List<Element> fieldElements = fieldsElement.elements("field");
		if(CollectionUtil.isNotEmpty(fieldElements)) {
			for (Element fieldElement : fieldElements) {
				DefaultEntityField entityField = parseEntityField(fieldElement);
				entity.addEntityField(entityField);
			}
		}
		
		// 解析virtual-field节点
		List<Element> virtualFieldElements = fieldsElement.elements("virtual-field");
		if(CollectionUtil.isNotEmpty(virtualFieldElements)) {
			for (Element virtualFieldElement : virtualFieldElements) {
				DefaultEntityField virtualEntityField = parseEntityField(virtualFieldElement);
				virtualEntityField.setVirtual(true);
				entity.addEntityField(virtualEntityField);
			}
		}
	}
	
	/**
	 * 解析<fields/>中的<field/>属性配置
	 * 
	 * @param fieldElement
	 * @return
	 */
	@SuppressWarnings({"rawtypes","unchecked"})
	private DefaultEntityField parseEntityField(Element fieldElement) throws Exception {
		DefaultEntityField entityField = new DefaultEntityField(fieldElement.attributeValue("name"), fieldElement.attributeValue("name"), 
				fieldElement.attributeValue("display"));
		String isNullable = fieldElement.attributeValue("isNullable");
		if(StringUtils.isNotBlank(isNullable)) {
			entityField.setNullable(Boolean.valueOf(isNullable));
		}
		String isDisplay = fieldElement.attributeValue("isDisplay");
		if(StringUtils.isNotBlank(isDisplay)) {
			entityField.setDisplay(Boolean.valueOf(isDisplay));
		}
		String defaultValue = fieldElement.attributeValue("defaultValue");
		if(StringUtils.isNotBlank(defaultValue)) {
			entityField.setValueGenerator(new DefaultFieldValueGenerator(defaultValue));
		}
		Element generatorEl = fieldElement.element("generator");
		if (generatorEl != null) {
			FieldValueGenerator fieldValueGenerator = null;
			String generatorClass = generatorEl.attributeValue("class");
			if (StringUtils.isNotBlank(generatorClass)) {
				Class clazz = Class.forName(generatorClass);
				String enableType = generatorEl.attributeValue("enableType");
				if(StringUtils.isNotBlank(enableType)) {
					Constructor constructor = clazz.getConstructor(new Class[]{GeneratorEnableType.class});
					fieldValueGenerator = (FieldValueGenerator)constructor.newInstance(GeneratorEnableType.valueOf(enableType));
				} else {
					fieldValueGenerator = (FieldValueGenerator)clazz.newInstance();
				}
			}
			String generatorBean = generatorEl.attributeValue("bean");
			if (StringUtils.isNotBlank(generatorBean)) {
				fieldValueGenerator = Application.getBeanContext().getBean(generatorBean, FieldValueGenerator.class);
			}
			entityField.setValueGenerator(fieldValueGenerator);
		}
		return entityField;
	}
	
	public static void main(String[] args) {
		System.out.println(Boolean.valueOf("true"));
	}

}
